项目功能实现:评论框插入表情 |
您所在的位置:网站首页 › 评论 表情包 › 项目功能实现:评论框插入表情 |
「本文已参与低调务实优秀中国好青年前端社群的写作活动」 问题一个 React 项目(用的函数组件)需要支持可以回复表情的评论,看到这个需求,相信读者们能想到好几种解决方案,比如使用成熟的富文本编辑器、使用第三方表情组件库、自己封装组件...... 考虑到开发成本不能太高、评论组件可以复用、需求只是支持表情即可,因此笔者选择了第二种解决方案,也就是说,要去技术调研以选择合适的第三方库。 技术选型GitHub 上有很多开源的表情库,对比了一下,个人觉得 emoji-mart 是最好的一个,原因: star 数达到了 5.4 k ; 使用文档清晰易懂,支持中文; 作者持续维护,可以看到上一次的 commit 时间是 5天 前; UI 设计高级,符合笔者审美。到这里,就确定了技术选型(出来吧 emoji-mart 就决定是你了hhh) 实践 安装表情组件库我们首先使用 npm install --save emoji-mart @emoji-mart/data 将库安装下来。 生成容器组件然后把 demo 跑起来,这里新建了一个 EmojiPicker.js 文件,用于生成容器组件,其代码如下: import React, { useEffect, useRef } from 'react'; import data from '@emoji-mart/data'; import { Picker } from 'emoji-mart'; function EmojiPicker(props) { const ref = useRef(); useEffect(() => { new Picker({ ...props, data, ref }); }, []); return ; } export default EmojiPicker;容器组件生成之后,就可以在其他地方使用,并调用它的 API 。在上面这段代码中,是不能在 div 中调用诸如 onEmojiSelect 之类的 API 的,因为此时容器组件还没生成,div 还仅仅只是 div 而已,这也是为什么要新建一个 EmojiPicker.js 的原因。 调用容器组件在评论框处调用 EmojiPicker ,即可在页面中看到效果了。 searchEmoji(emoji)} /> 这里只展示与表情组件库有关联的输入框,其他相关组件的布局这里就不一一写出来了,请读者自由发挥 onChatContentChange(e.target.value)} // 文本值发生改变时的回调 />到这里,我们离成功实现评论功能迈进了一小步,但还不够,可以看到上面代码有三个动态数据,分别是一个 chatContent 字段、onChatContentChange 函数和 searchEmoji 函数,我们继续往(写)下(bug)。 封装函数 第一版在输入框进行键盘输入和表情插入,我们可以想到这样的逻辑: ①键盘输入时直接调用输入框的 onChange API 更新文本值 chatContent 即可 ②插入表情时调用组件库的 onEmojiSelect API 获取到要插入的表情,拼接到 chatContent 后面于是有了下面的代码: const [chatContent, setChatContent] = useState(''); // ①输入框文本值发生改变的回调函数 const onChatContentChange = (value) => { setChatContent(value); }; // ②选中表情的回调函数 const searchEmoji = (emoji) => { // 考虑到在一开始就插入表情的情况 const newChatContent = chatContent.length > 0 ? chatContent + emoji.native : emoji.native; setChatContent(newChatContent); };然而这版的代码是有 bug 的,假如先输入“你好”,再插入表情,预计结果应该是“你好【表情】”,然而实际结果是“【表情】”,如图所示:
为什么会这样呢?这是因为 chatContent.length 为 0 ,自然就被赋值为 emoji.native 了。那么,在 @飞哥 的提点下,用 tempTextAreaData 全局字段存储输入框的文本值,这样就可以在页面更新的时候依然也能拿到最新的文本值,因此代码变成这样: + let tempTextAreaData = ''; const [chatContent, setChatContent] = useState(''); // ①输入框文本值发生改变的回调函数 const onChatContentChange = (value) => { setChatContent(value); + tempTextAreaData = value; }; // ②选中表情的回调函数 const searchEmoji = (emoji, event) => { // 考虑到在一开始就插入表情的情况 - const newChatContent = chatContent.length > 0 ? chatContent + emoji.native : emoji.native; + const newChatContent = tempTextAreaData.length > 0 ? tempTextAreaData + emoji.native : emoji.native; + tempTextAreaData = newChatContent; setChatContent(newChatContent); };来看看效果:
我们完成了第一版的代码,实现了在输入框文本值后面插入表情,但有一个缺陷:不能在文本中间插入表情,因此我们的代码逻辑需要进一步完善。 笔者的思考方向是这样的:当光标移动到文本中间时,获取这个光标的位置,截断光标之前和光标之后的字符,将表情拼接到两者之间。 onChatContentChange 函数比较简单,第一版已经搞定了,现在我们完善 searchEmoji 函数: // 由于在光标中间拼接表情稍微复杂了一点,这里单独抽成 insertAtCursor 函数,tempTextAreaData 的更新也将在 insertAtCursor 中完成 const searchEmoji = (emoji) => { let dom = document.getElementById('textarea'); // 获取输入框的节点对象 insertAtCursor(dom, emoji.native); // 将表情插入到光标后面 };insertAtCursor 函数: const insertAtCursor = (myField, myValue) => { if (document.selection) { //IE support myField.focus(); const sel = document.selection.createRange(); sel.text = myValue; sel.select(); } else if (myField.selectionStart || myField.selectionStart == '0') { //MOZILLA/NETSCAPE support const startPos = myField.selectionStart; const endPos = myField.selectionEnd; const beforeValue = myField.value.substring(0, startPos); const afterValue = myField.value.substring(endPos, myField.value.length); tempTextAreaData = beforeValue + myValue + afterValue; setChatContent(tempTextAreaData); myField.selectionStart = startPos + myValue.length; myField.selectionEnd = startPos + myValue.length; myField.focus(); } else { tempTextAreaData += myValue; setChatContent(tempTextAreaData); myField.focus(); } }这样一来,就可以在文本中插入表情了,效果如图: 在第二版代码完成之后,这个项目需求就完成了,当然,这样的实现是基于这个评论功能只需要支持表情就好,对于图片的插入、上传等是不支持的,如果确实需要支持图片的话,其实可以考虑富文本编辑器,工具栏简洁一点,支持图片和表情,也就可以了。 关于富文本编辑器的技术选型,可以参考这篇文章:前端开发常用的10款富文本编辑器。 希望读者们能多多支持这个项目: onepiece-web(star 一下不亏的 ^_^) 以上就是全部内容了,希望对大家有所帮助~ |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |